package com.qimu.saiyou.controller;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qimu.saiyou.common.BaseResponse;
import com.qimu.saiyou.common.ErrorCode;
import com.qimu.saiyou.common.PageRequest;
import com.qimu.saiyou.common.ResultUtils;
import com.qimu.saiyou.exception.BusinessException;
import com.qimu.saiyou.manager.RedisLimiterManager;
import com.qimu.saiyou.model.dto.friendsapply.FriendApplyRequest;
import com.qimu.saiyou.model.entity.FriendsApply;
import com.qimu.saiyou.model.entity.User;
import com.qimu.saiyou.model.enums.FriendApplyStatusEnum;
import com.qimu.saiyou.model.vo.FriendApplyVo;
import com.qimu.saiyou.model.vo.UserVO;
import com.qimu.saiyou.service.FriendsApplyService;
import com.qimu.saiyou.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.qimu.saiyou.model.enums.FriendApplyStatusEnum.DEFAULT_STATUS;
import static com.qimu.saiyou.model.enums.FriendApplyStatusEnum.EXPIRED_STATUS;

/**
 * 好友申请
 *
 *@author: FeiXiang
 * 
 */
@RestController
@RequestMapping("/friendsApply")
@Slf4j
public class FriendsApplyController {
    @Resource
    private FriendsApplyService friendsApplyService;
    @Resource
    private UserService userService;
    @Resource
    private RedisLimiterManager redisLimiterManager;

    // region 增删改查

    @PostMapping("apply")
    public BaseResponse<Boolean> applyFriend(@RequestBody FriendApplyRequest friendApplyRequest, HttpServletRequest request) {
        if (friendApplyRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        boolean addStatus = friendsApplyService.applyFriend(loginUser, friendApplyRequest);
        return ResultUtils.success(addStatus);
    }

    @PostMapping("agreed")
    public BaseResponse<Boolean> agreedFriend(long id, HttpServletRequest request) {
        if (id < 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        boolean agreedFriend = friendsApplyService.agreedFriend(loginUser, id);
        return ResultUtils.success(agreedFriend);
    }

    @PostMapping("refused")
    public BaseResponse<Boolean> refusedFriend(long id, HttpServletRequest request) {
        if (id < 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        boolean refusedFriend = friendsApplyService.refusedFriend(loginUser, id);
        return ResultUtils.success(refusedFriend);
    }

    /**
     * 撤销好友
     *
     * @param id      身份证件
     * @param request 要求
     * @return {@link BaseResponse}<{@link Boolean}>
     */
    @PostMapping("revoke")
    public BaseResponse<Boolean> revokeFriend(long id, HttpServletRequest request) {
        if (id < 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        boolean revokeFriend = friendsApplyService.revokeFriend(loginUser, id);
        return ResultUtils.success(revokeFriend);
    }

    @PostMapping("/list/vo/my/apply")
    public BaseResponse<Page<FriendApplyVo>> myApplyRecord(@RequestBody PageRequest pageRequest, HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        int current = pageRequest.getCurrent();
        int pageSize = pageRequest.getPageSize();
        String sortField = pageRequest.getSortField();
        String sortOrder = pageRequest.getSortOrder();
        LambdaQueryWrapper<FriendsApply> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(FriendsApply::getFromId, loginUser.getId());
        Page<FriendsApply> friendsApplyPage = friendsApplyService.page(new Page<>(current, pageSize), lambdaQueryWrapper);
        List<FriendApplyVo> friendApplyVoList = friendsApplyPage.getRecords().stream().map(friendsApply -> {
                    FriendApplyVo friendApplyVo = new FriendApplyVo();
                    BeanUtils.copyProperties(friendsApply, friendApplyVo);
                    User user = userService.getById(friendsApply.getReceiveId());
                    UserVO userVO = new UserVO();
                    BeanUtils.copyProperties(user, userVO);
                    friendApplyVo.setApplyUser(userVO);
                    if (friendApplyVo.getStatus().equals(DEFAULT_STATUS.getValue()) && DateUtil.between(new Date(), friendsApply.getCreateTime(), DateUnit.DAY) >= 3) {
                        friendApplyVo.setStatus(EXPIRED_STATUS.getValue());
                    }
                    return friendApplyVo;
                }).sorted(Comparator.comparing(FriendApplyVo::getCreateTime)
                        .reversed())
                .collect(Collectors.toList());
        Page<FriendApplyVo> friendApplyVoPage = new Page<>(friendsApplyPage.getCurrent(), friendsApplyPage.getSize(), friendsApplyPage.getTotal());
        friendApplyVoPage.setRecords(friendApplyVoList);
        return ResultUtils.success(friendApplyVoPage);
    }

    @PostMapping("/list/vo/my/receiving")
    public BaseResponse<Page<FriendApplyVo>> myReceivingRecord(@RequestBody PageRequest pageRequest, HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        int current = pageRequest.getCurrent();
        int pageSize = pageRequest.getPageSize();
        LambdaQueryWrapper<FriendsApply> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(FriendsApply::getReceiveId, loginUser.getId());
        Page<FriendsApply> friendsApplyPage = friendsApplyService.page(new Page<>(current, pageSize), lambdaQueryWrapper);
        List<FriendApplyVo> friendApplyVoList = friendsApplyPage.getRecords().stream().map(friendsApply -> {
                    FriendApplyVo friendApplyVo = new FriendApplyVo();
                    BeanUtils.copyProperties(friendsApply, friendApplyVo);
                    User user = userService.getById(friendsApply.getFromId());
                    UserVO userVO = new UserVO();
                    BeanUtils.copyProperties(user, userVO);
                    friendApplyVo.setApplyUser(userVO);
                    if (friendApplyVo.getStatus().equals(DEFAULT_STATUS.getValue()) && DateUtil.between(new Date(), friendsApply.getCreateTime(), DateUnit.DAY) >= 3) {
                        friendApplyVo.setStatus(EXPIRED_STATUS.getValue());
                    }
                    return friendApplyVo;
                }).sorted(Comparator.comparing(FriendApplyVo::getCreateTime)
                        .reversed())
                .collect(Collectors.toList());
        Page<FriendApplyVo> friendApplyVoPage = new Page<>(friendsApplyPage.getCurrent(), friendsApplyPage.getSize(), friendsApplyPage.getTotal());
        friendApplyVoPage.setRecords(friendApplyVoList);
        return ResultUtils.success(friendApplyVoPage);
    }


    @PostMapping("/read")
    public BaseResponse<Boolean> read(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        List<FriendsApply> friendsNotReadList = friendsApplyService.lambdaQuery()
                .eq(FriendsApply::getReceiveId, loginUser.getId())
                .eq(FriendsApply::getIsRead, FriendApplyStatusEnum.NOT_READ)
                .list()
                .stream()
                .peek(friendsApply -> friendsApply.setIsRead(FriendApplyStatusEnum.READ.getValue()))
                .collect(Collectors.toList());
        boolean flag = friendsApplyService.updateBatchById(friendsNotReadList);
        return ResultUtils.success(flag);
    }

    @GetMapping("/notRead/count")
    public BaseResponse<Long> notReadCount(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        Long count = friendsApplyService.lambdaQuery()
                .eq(FriendsApply::getReceiveId, loginUser.getId())
                .eq(FriendsApply::getIsRead, FriendApplyStatusEnum.NOT_READ)
                .count();
        return ResultUtils.success(count);
    }
}
